#include "llDependence.hpp"
#include "llToken.hpp"
using namespace llmake;

#include <boost/filesystem.hpp>
using namespace boost::filesystem;

#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>

llDependenceNode::llDependenceNode(const string & name)
 :m_FileName(name)
 ,m_TimeStamp(0)
{
	path full_path(m_FileName);
	if( exists(full_path) && is_regular_file(full_path) )
	{
		m_TimeStamp = last_write_time(full_path);
	}
}
void llDependenceNode::update(void)
{
	path full_path(m_FileName);
	if( exists(full_path) && is_regular_file(full_path) )
	{
		m_TimeStamp = last_write_time(full_path);
	}
}

void llDependenceEngine::save(void)
{
// update time stamp of all files 
	llDependenceMap::iterator ir = m_CurDep.begin();
	for( ; m_CurDep.end() != ir ; ir++ )
	{
		ir->second.update();
	}
// write time stamp to serialize
    // make an archive
	std::ofstream ofs(m_XmlSerialize.c_str());
    assert(ofs.good());
    boost::archive::xml_oarchive oa(ofs);
	m_LastDep = m_CurDep;
    oa << BOOST_SERIALIZATION_NVP(m_LastDep);
}

void llDependenceEngine::load(void)
{
	path full_path(m_XmlSerialize);
	if( false == exists(full_path) )
	{
		return;
	}
    // open the archive
    std::ifstream ifs(m_XmlSerialize.c_str());
    assert(ifs.good());
    boost::archive::xml_iarchive ia(ifs);

    ia >> BOOST_SERIALIZATION_NVP(m_LastDep);
}

bool llDependenceEngine::parseDependence(list<string> &first,list<string> &remains)
{
	bool ret = true;
	list<llDependenceNode> remainNode;
	list<string>::iterator remainIt = remains.begin();
	for( ; remains.end() != remainIt ; remainIt++ )
	{
#ifdef DEGUB
		cout<<"remains "<<*remainIt<<endl;
#endif
		llTokenEngine remainToken(*remainIt,false);
		remainToken.setSpilitor(" ","");
		llTokenList tokens;
		remainToken.getToken(tokens);
		llTokenList::iterator tokenIt = tokens.begin();
		for( ; tokens.end() != tokenIt ; tokenIt++ )
		{
#ifdef DEGUB
			cout<<"llDependenceNode  "<<tokenIt->m_Token<<endl;
#endif
			llDependenceNode node(tokenIt->m_Token);
			remainNode.push_back(node);
		}
	}

	list<string>::iterator firstIt = first.begin();
	for( ; first.end() != firstIt ; firstIt++ )
	{
#ifdef DEGUB
		cout<<"first "<<*firstIt<<endl;
#endif
		llTokenEngine firstToken(*firstIt,false);
		firstToken.setSpilitor(" ","");
		llTokenList tokens;
		firstToken.getToken(tokens);
		llTokenList::iterator tokenIt = tokens.begin();
		for( ; tokens.end() != tokenIt ; tokenIt++ )
		{
#ifdef DEGUB
			cout<<"llDependencePair  "<<tokenIt->m_Token<<endl;
#endif
			llDependenceNode node(tokenIt->m_Token);
			llDependencePair depPair(node,remainNode);
			llDependenceMap::iterator ir = m_CurDep.find(tokenIt->m_Token);
			if( m_CurDep.end() == ir )
			{
				m_CurDep[tokenIt->m_Token] = depPair;
			}
			else
			{
				ir->second.append(remainNode);
			}
			llDependenceMap::iterator newIr = m_CurDep.find(tokenIt->m_Token);
			llDependenceMap::iterator lastIr = m_LastDep.find(tokenIt->m_Token);
			if( m_LastDep.end() == lastIr )
			{
				ret = true;
			}
			else
			{
				if( newIr->second == lastIr->second )
				{
					ret = false;
				}
				else
				{
					ret = true;
				}
			}
		}
	}
	return ret;
}
